package com.fulihui.information.core.repository.impl;

import com.fulihui.information.biz.conv.ContentConv;
import com.fulihui.information.common.ESortType;
import com.fulihui.information.common.config.AppConst;
import com.fulihui.information.core.db.ContentTopDB;
import com.fulihui.information.core.repository.ContentRepository;
import com.fulihui.information.dal.dataobj.InfoContent;
import com.fulihui.information.dal.dataobj.InfoContentExample;
import com.fulihui.information.dal.mapper.ExtInfoContentListItemMapper;
import com.fulihui.information.dal.mapper.ExtInfoContentMapper;
import com.fulihui.information.dal.mapper.InfoContentMapper;
import com.fulihui.information.dto.ContentDTO;
import com.fulihui.information.dto.ContentListItemDTO;
import com.fulihui.information.enums.EContentSortFields;
import com.fulihui.information.enums.EContentStatus;
import com.fulihui.information.enums.EYesOrNo;
import com.fulihui.information.request.ContentPageQueryRequest;
import com.fulihui.information.request.ModifyContentRequest;
import org.near.servicesupport.error.Errors;
import org.near.servicesupport.error.InvokeServiceException;
import org.near.toolkit.common.DateUtils;
import org.near.toolkit.common.EnumUtil;
import org.near.toolkit.common.StringUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Repository;
import org.springframework.transaction.annotation.Transactional;

import java.text.ParseException;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Set;

import static com.fulihui.information.biz.conv.ContentConv.toDTO;
import static com.fulihui.information.biz.conv.ContentConv.toList;
import static org.near.toolkit.common.StringUtil.isBlank;
import static org.near.toolkit.common.StringUtil.isNotBlank;

/**
 * @author LeeSon on 2016/12/28 0028.
 */
@Repository
public class ContentRepositoryImpl implements ContentRepository {
    @Autowired
    private InfoContentMapper            infoContentMapper;
    @Autowired
    private ExtInfoContentMapper         extInfoContentMapper;
    @Autowired
    private ExtInfoContentListItemMapper extInfoContentListItemMapper;
    @Autowired
    @Qualifier("redisContentTopDB")
    private ContentTopDB                 contentTopDB;

    /**
     * @see ContentRepository#batchModifyStatus(Set, String, String)
     */
    @Override
    public boolean batchModifyStatus(Set<String> ids, String status, String operator) {
        InfoContentExample example = new InfoContentExample();
        example.createCriteria().andIdIn(new ArrayList<>(ids));
        InfoContent record = new InfoContent();
        record.setStatus(status);
        record.setOperator(operator);
        // 如果是下架状态或者删除状态，将置顶状态页置成未置顶
        if (EContentStatus.DELETE.getCode().equals(status)
                || EContentStatus.UNCHECK.getCode().equals(status)) {
            record.setTopStatus("0");
        }
        return infoContentMapper.updateByExampleSelective(record, example) > 0;
    }

    /**
     * @see ContentRepository#modifyContent(ModifyContentRequest)
     */
    @Override
    public boolean modifyContent(ModifyContentRequest request) {
        // TODO 修改以后实现...
        return true;
    }

    /**
     * @see ContentRepository#setTop(String, String, String)
     */
    @Override
    @Transactional
    public void setTop(String contentId, String categoryCode, String operator) {
        InfoContent record;
        int rs;
        // 将原本置顶的设置成非置顶的
        record = new InfoContent();
        record.setTopStatus(EYesOrNo.NO.getCode());
        InfoContentExample example = new InfoContentExample();
        example.createCriteria()
                // XXX 目前只支持热门置顶，将所有类目的置顶去掉
                //.andCategoryCodeEqualTo(categoryCode)
                .andTopStatusEqualTo(EYesOrNo.YES.getCode());
        infoContentMapper.updateByExampleSelective(record, example);

        // 置顶已选择的资讯
        record = new InfoContent();
        record.setId(contentId);
        record.setOperator(operator);
        record.setTopStatus(EYesOrNo.YES.getCode());
        rs = infoContentMapper.updateByPrimaryKeySelective(record);
        if (rs == 0) {
            throw new InvokeServiceException(Errors.Commons.SYSTEM_ERROR);
        }

    }

    @Override
    public List<ContentDTO> queryPage(ContentPageQueryRequest request) {
        int start = request.start4Mysql();
        int rows = request.getRows();
        InfoContent topVal = null;
        // XXX 目前只支持热点置顶
        ContentListItemDTO item = contentTopDB.getTop(AppConst.CONTENT_HOTS_CATEGORY_CODE);
        boolean appendTop = false;
        if (item != null && (EContentStatus.CHECK.getCode().equals(request.getStatus())
                || isBlank(request.getStatus()))) {
            // 确保缓存中的数据在数据库中还存在
            topVal = infoContentMapper.selectByPrimaryKey(item.getId());
            // 后台分页查询类目中有置顶才处理
            if (topVal != null && topVal.getCategoryCode().equals(request.getCategoryCode())) {
                // 第一页有置顶数据存放置顶数据，后面几页会对第一页的置顶数据做处理
                if (start == 0) {
                    rows = rows - 1;
                    appendTop = true;
                } else { // 非第一页在有置顶数据的情况下，分页查询起始位减1
                    start = start - 1;
                }
            } else {
                // TODO [huwei] 数据库中已不存在或修改，删除缓存
            }
        }
        InfoContentExample example = buildInfoContentExample(request);
        // 置顶数据要被过滤
        example.getOredCriteria().get(0).andTopStatusEqualTo("0");
        List<InfoContent> infoContentList = extInfoContentMapper.selectByExamplePage(example, start, rows);
        if (appendTop) {
            infoContentList.add(0, topVal);
        }
        return ContentConv.toList(infoContentList, ContentDTO.class);
    }

    @Override
    public int queryPageCount(ContentPageQueryRequest request) {
        return extInfoContentMapper.selectByExamplePageCount(buildInfoContentExample(request));
    }

    @Override
    public ContentDTO detail(String id) {
        InfoContent infoContent = infoContentMapper.selectByPrimaryKey(id);
        return toDTO(infoContent, ContentDTO.class);
    }

    private InfoContentExample buildInfoContentExample(ContentPageQueryRequest request) {
        try {
            InfoContentExample example = new InfoContentExample();
            InfoContentExample.Criteria criteria = example.createCriteria();

            if (isNotBlank(request.getCategoryCode())) {
                criteria.andCategoryCodeEqualTo(request.getCategoryCode());
            }

            if (isNotBlank(request.getTimeStart())) {
                criteria.andGmtCreateGreaterThanOrEqualTo(DateUtils.parseWebFormat(request.getTimeStart()));
            }

            if (isNotBlank(request.getTimeEnd())) {
                Date date = DateUtils.parseWebFormat(request.getTimeEnd());
                date.setHours(23);
                date.setMinutes(59);
                date.setSeconds(59);
                criteria.andGmtCreateLessThanOrEqualTo(date);
            }

            if (isNotBlank(request.getTitle())) {
                criteria.andTitleLike(request.getTitle() + "%");
            }

            if (isNotBlank(request.getStatus())) {
                criteria.andStatusEqualTo(request.getStatus());
            }

            if (isNotBlank(request.getSortFiled())) {
                // 类型在Service中已经校验，此时一定能转换成功，将入参领域参数名转换成表列名
                String sortField = EnumUtil.queryByCode(request.getSortFiled(),
                        EContentSortFields.class).getDesc();
                example.setOrderByClause(sortField + (isBlank(request.getSortType())
                        ? "" : (" " + request.getSortType())));
            } else {
                example.setOrderByClause(EContentSortFields.GMT_CREATE.getDesc()
                        + " " + ESortType.DESC.getCode());
            }

            if(StringUtil.isNotBlank(request.getSourceCode())) {
                criteria.andSourceCodeEqualTo(request.getSourceCode());
            }

            return example;
        } catch (ParseException e) {
            throw new RuntimeException(e);
        }
    }

    /**
     * @see ContentRepository#queryItemListPage(int, int, InfoContentExample)
     */
    @Override
    public List<ContentListItemDTO> queryItemListPage(int start, int rows, InfoContentExample example) {
        List<InfoContent> contentList = extInfoContentListItemMapper.selectListItemPage(example, start, rows);
        return toList(contentList, ContentListItemDTO.class);
    }

    /**
     * @see ContentRepository#queryItemListCount(InfoContentExample)
     */
    @Override
    public Long queryItemListCount(InfoContentExample example) {
        return extInfoContentListItemMapper.selectListItemCount(example);
    }

    /**
     * @see ContentRepository#queryItemListByIds(List)
     */
    @Override
    public List<ContentListItemDTO> queryItemListByIds(List<String> ids) {
        List<InfoContent> contentList = extInfoContentListItemMapper.selectListItemByIds(ids);
        return toList(contentList, ContentListItemDTO.class);
    }

    /**
     * @see ContentRepository#queryItemListById(String)
     */
    @Override
    public ContentListItemDTO queryItemListById(String id) {
        return toDTO(extInfoContentListItemMapper.selectListItemById(id), ContentListItemDTO.class);
    }

}
